package impl

import (
	"context"
	"log"

	"gitee.com/go-course/go11/devcloud-mini/cmdb/apps/resource"
	"gitee.com/go-course/go11/devcloud-mini/cmdb/apps/secret"
	"gitee.com/go-course/go11/devcloud-mini/cmdb/provider"
	"gitee.com/go-course/go11/devcloud-mini/cmdb/provider/tencent/cvm"
	"go.mongodb.org/mongo-driver/bson"
)

// 创建同步凭证
func (i *impl) CreateSecret(ctx context.Context, in *secret.Spec) (
	*secret.Secret, error) {
	ins, err := secret.NewSecret(in)
	if err != nil {
		return nil, err
	}

	// 自己补充校验规则
	_, err = i.col.InsertOne(ctx, ins)
	if err != nil {
		return nil, err
	}
	return ins, nil
}

// 查询同步凭证
func (i *impl) QuerySecret(ctx context.Context, in *secret.QuerySecretRequest) (
	*secret.SecretSet, error) {
	return nil, nil
}

// 查询凭证详情
func (i *impl) DescribeSecret(ctx context.Context, in *secret.DescribeSecretRequest) (
	*secret.Secret, error) {
	ins := &secret.Secret{}
	err := i.col.FindOne(ctx, bson.M{"_id": in.Id}).Decode(ins)
	if err != nil {
		return nil, err
	}

	err = ins.Spec.Decrypt()
	if err != nil {
		return nil, err
	}
	return ins, nil
}

// 流式接口, 便同步边返回
// host 01 已经同步
// host 02 已经同步 。。。
// 1. secret id 查询出secret对象
// 2. 使用scret id 初始化一个provider
// 3. 使用这个provider进行资源的同步
func (i *impl) SyncResource(
	in *secret.SyncResourceRequest,
	stream secret.Rpc_SyncResourceServer) error {
	ctx := stream.Context()
	// 1. secret id 查询出secret对象
	ins, err := i.DescribeSecret(ctx, &secret.DescribeSecretRequest{
		Id: in.SecretId,
	})
	if err != nil {
		return err
	}

	switch ins.Spec.Provider {
	case resource.PROVIDER_TENCENT:
		for _, region := range ins.Spec.ResourceRegions {
			// 2. 使用scret id 初始化一个provider
			cvmPd, err := cvm.NewCVMClient(ins.Spec.ApiKey, ins.Spec.ApiSecret, region)
			if err != nil {
				return err
			}
			// 3. 使用这个provider进行资源的同步
			cvmPd.QueryHost(ctx, provider.NewQueryHostRequest(), func(r *resource.Resource) {
				resp := &secret.SyncResourceResponse{
					ResourceId: r.Meta.Id,
				}

				res, err := i.resource.CreateResource(ctx, r)
				// 通过的结果就需要通过Response返回
				if err != nil {
					resp.Message = err.Error()
				} else {
					resp.Successed = true
					resp.Message = res.ShortDesc()
				}

				err = stream.Send(resp)
				if err != nil {
					log.Print(err)
				}
			})
		}
	}

	return nil
}
